package com.apes.fn.server.servicePlan.model;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.annotation.JSONField;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.fn.server.workOrder.repository.MaintenanceOrderRepository;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.BaseModel;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.fileserver.File;
import com.apes.framework.plugin.soe.annotations.State;
import com.apes.framework.plugin.soe.annotations.States;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.util.*;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.finance.model.CrossIC;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.product.model.Category;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.model.ServeType;
import com.apes.scm.masterdata.stock.model.Location;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Creator: zouyc
 * CreateDate: 2019-12-30 15:56
 * Description:
 **/
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = ServicePlanItem.CONST_TABLE_NAME)
public class ServicePlanItem extends BaseModel {
    public static final String CONST_TABLE_NAME = "ser_service_plan_item";

    @Id
    @Column(name = "id", nullable = false, length = 24)
    @ApesGenerator(code = CONST_TABLE_NAME, name = "方案从表编码", padding = 12)
    private String id;

    @Column(name = "sort", length = 250)
    @Comment("排序字段")
    private Integer sort;

    @ManyToOne(optional = false)
    @JoinColumn(name = "service_plan_id", referencedColumnName = "id")
    @Comment("主表编码")
    private ServicePlan servicePlan;

    public void setParentServicePlanItem(ServicePlanItem parentServicePlanItem) {
        this.parentServicePlanItem = parentServicePlanItem;
    }

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_item_id")
    @Comment("来源方案明细行")
    private ServicePlanItem parentServicePlanItem;

    @Column(name = "inner_item_id", length = 24)
    @Comment("内协方案明细")
    private String innerServicePlanItem;

    @Column(name = "higher_level_code", length = 24)
    @Comment("上级商品编码")
    private String higherLevelCode;

    @Column(name = "price_source", length = 24)
    @Comment("价格来源日志编码")
    private String priceSource;

    @States(name = "服务状况", values = {
            @State(id = "false", name = "不同意服务"),
            @State(id = "true", name = "同意服务")
    })
    @Column(name = "service_state", nullable = false, columnDefinition = "number(1,0) default 1")
    private boolean serviceState = true;

    @Transient
    private Integer serviceStateInt;
    public Integer getServiceStateInt(){
        return this.serviceState ? 1 : 0;
    }

    @States(name = "评估状况", values = {
            @State(id = "true", name = "必修"),
            @State(id = "false", name = "隐患")
    })
    @Column(name = "assessment_situation", nullable = false, columnDefinition = "number(1,0) default 1")
    @Comment("评估状况")
    private boolean assessmentSituation = true;

    @Transient
    private String stateName;

    public String getStateName() {
        StringBuffer sf = new StringBuffer();
        if (Objects.isNull(state)) return null;
        switch (state){
            case "create":
                if (this.servicePlan.getSubmissionDate()!=null&&this.servicePlan.getConfirmDate()!=null)return "提交";
                if (this.servicePlan.getGoBackDate()!=null)return "退回";
                if (this.servicePlan.getState().equals("toPriceAudit"))return "价格审核中";
                if (this.servicePlan.getPriceAuditDate() !=null)return "价格通过";
                if (this.servicePlan.getBackPriceAuditDate() !=null)return "价格退回";
                return "新增";
            case "confirm":
                if (this.qtyReceive == Arith.sub(this.saleQty,this.qtyEnd)) return "已质检";
                if (this.assistType.getName().equals("内协"))sf.append("内协");
                sf.append(findWorkStateName());
                return sf.toString();
            case "termination":
                return "终止";
                default:return "";
        }
    }

    // 要货前端显示
    @Transient
    private Map requireView;
    // 领用前端显示
    @Transient
    private Map qtyReceiveView;

    //要货备注
//    @Transient
//    private String requireRemark;
//
//    @Transient
//    private Double requireQtyTemp = 0.0D;
//
//    public void addRequireQtyTemp(Double qty){
//        requireQtyTemp +=qty;
//    }
//
//    @Transient
//    private Double qtyReceiveOrder = 0.0D;
//
//    public void addQtyReceiveOrder(Double qty){
//        qtyReceiveOrder +=qty;
//    }
//
//    public void setRequireRemark(String requireRemark) {
//
//        if (this.requireRemark==null)this.requireRemark = "";
//        if (!this.requireRemark.contains(requireRemark))
//            this.requireRemark = this.requireRemark + requireRemark;
//    }


    @States(name = "明细状态", values = {
            @State(id = "create", name = "新增"),
            @State(id = "confirm", name = "确认"),
            @State(id = "termination", name = "终止")
    })
    @Column(name = "state", length = 32)
    private String state = "create";

    public String findWorkStateName() {
        if (workState==null)return "待施工";
        switch (workState){
            case "wait":
                return "待施工";
            case "working":
                return "施工中";
            case "pause":
                return "暂停施工";
            case "waitDispatch":
                return "采购派工中";
            case "back":
                return "外协退回";
            case "dispatch":
                return "派工完成";
            case "treatQuality":
                return "待质检";
            case "quality":
                return "已质检";
            case "termination":
                return "终止";
                default: return workState;
        }
    }

    @States(name = "施工状态", values = {
            @State(id = "wait", name = "待施工"),
            @State(id = "working", name = "施工中"),
            @State(id = "pause", name = "暂停施工"),
            @State(id = "waitDispatch", name = "待派工"),
            @State(id = "back", name = "退回"), // 外协退回
            @State(id = "dispatch", name = "派工成功"),
            @State(id = "treatQuality", name = "待质检"), // 完工
            @State(id = "quality", name = "质检"),
            @State(id = "termination", name = "终止")
    })
    @Column(name = "work_state", length = 32)
    private String workState = "wait";

    @Column(name = "qty_delivery", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("到货数量")
    private double qtyDelivery = 0;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id", referencedColumnName = "id")
    @Comment("商品")
    private Product product;

    @Transient
    @Comment("异业父类")
    private Map crossICP;
    public Map getCrossICP(){
        if(this.crossIC != null && crossIC.getCrossId() != null) return MapUtil.mapper("id",this.getCrossIC().getCrossId(),"name",this.getCrossIC().getCrossName());
        return null;
    }

    @Transient
    @Comment("品类")
    private Category category ;
    public Category getCategory(){
        if(this.fitting != null) return  this.fitting;
        if(this.product != null) return this.product.getCategory();
        return null;
    }

    public String getProductName() {
        if(this.product != null) return this.product.getName();
        return productName;
    }

    @Transient
    @Comment("商品名称")
    private String productName ;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fitting", referencedColumnName = "id")
    @Comment("配件")
    private Category fitting;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_uom_id", referencedColumnName = "id")
    @Comment("计量单位编码")
    private ProductUom uom;

    @Column(name = "sale_qty", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("销售数量")
    private double saleQty = 0;

    @Transient
    private double oldSaleQty = 0;

    public double getOldSaleQty() {
        return saleQty;
    }


    @Column(name = "qty_require", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("要货数量")
    private double qtyRequire = 0;

    @Column(name = "qty_receive", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("领用数量")
    private double qtyReceive = 0;

    @Column(name = "qty_voucher", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("带安凭证数量")
    private double qtyVoucher = 0;

    public void addQtyVoucher(double qty){
        this.qtyVoucher += qty;
        if (this.qtyVoucher > this.saleQty) throw new RuntimeException("写入凭证的数据不能大于销售数量");

    }

    public void addQtyReceive(Double qty) {
        if(!this.isServiceState()) throw new RuntimeException("终止商品不能领用");
        this.qtyReceive += qty;
        if (this.saleQty - this.qtyEnd < this.qtyReceive || this.qtyReceive < 0) {
            throw new RuntimeException("领用数不允许大于可领用数量或小于0");
        }
    }

    @Column(name = "qty_end", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("终止数量")
    private double qtyEnd = 0;

    @Transient
    private double qtyEndTemp; //前端传过来的终止数量

    @Column(name = "primary_price_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("零售价")
    private double primaryPriceUnit = 0;

    @Column(name = "price_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("销售单价")
    private double priceUnit = 0;

    @Column(name = "primary_price_unit_show", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("原销售单价展示")
    private double  primaryPriceUnitShow = 0;

    @Column(name = "pft_price_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("优惠单价")
    private double pftPriceUnit = 0;  //通过价格审核后的

    @Column(name = "pft_price_unit_c", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("优惠单价(异业回原值用)")
    private double pftPriceUnitCross = 0; //用于异业控制（方案确认后，这个值不做更改，防止异业值过高，导致卖价变了，第二次降低回不到原值）
    public double getPftPriceUnitCross(){
        if(this.pftPriceUnitCross == 0 && this.getServicePlan() != null &&  this.getServicePlan().getConfirmDate() != null) return this.pftPriceUnit;
        return pftPriceUnitCross;
    }

    public double getPftPriceUnit(){ //改结果保留两位小数向上取整
        return Arith.roundUp(this.pftPriceUnit,2);
    }

    public void setSalesAmount(double salesAmount) {
        this.salesAmount = salesAmount;
        if (this.crossIC==null){
            this.realPayAmount = this.salesAmount;
        }
    }

    @Column(name = "sales_amount", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("销售金额")
    private double salesAmount = 0;

    @Column(name = "management_fee_rate", nullable = false, columnDefinition = ApesConst.FIELD_ROUND_16_8)
    @Comment("管理费率")
    private double managementFeeRate = 0;

    @Column(name = "management_cost", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("管理费用")
    private double managementCost = 0;

    public double calcalateManagementCost() {
        return Arith.round(Arith.mul(Arith.mul(this.getPftPriceUnit(), this.getManagementFeeRate()), this.getSaleQty() - this.qtyEnd), 0);
    }

    @Column(name = "supply_Chain_Management", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("供应链管理费用")
    private double supplyChainManagement = 0;

    @Column(name = "floor_price", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("最低限价")
    private double floorPrice = 0;

    @Column(name = "clerk_price_limmit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("店员限价")
    private double clerkPriceLimit = 0;

    @Column(name = "shop_owner_price_limit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("店长限价")
    private double shopOwnerPriceLimit = 0;

    @Column(name = "cso_price_limit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("销售总监限价")
    private double csoPriceLimit = 0;

    @Column(name = "base_price", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("销售基准价")
    private double basePrice = 0;

    @Column(name = "discount_rate", nullable = false, columnDefinition = ApesConst.FIELD_ROUND_16_8)
    @Comment("折扣率")
    private double discountRate = 0;
    public double calculateDiscountRate(){
        if (this.getPrimaryPriceUnitShow()==0)return 0;
        try {
            return Arith.round(Arith.div(this.getPftPriceUnit(),this.getPrimaryPriceUnit()),4);
        } catch (Exception e) {
            throw new RuntimeException("计算折扣率错误");
        }
    }

    /**
     *
     * @author czs
     * @creed: 目前只有卡内在用,
     * 参数传递:方案明细 -> 服务工单 -> 外协工单
     * @date  2023年6月27日 11:08:30
     */
    @Column(name = "platform_purchase_cost", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("平台采购成本单价")
    private double platformPurchaseCost = 0;

    /**
     * 确认的时候会带到服务工单里 外协派工生成外协东单的时候会取工单里的成本单价(外协)
     */
    @Column(name = "platform_price_cost_in_tax", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("平台成本单价")
    private double platformPriceCosInTax = 0;

    @Column(name = "price_cost_unit_in_tax", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("含税成本单价")
    private double priceCostUnitInTax = 0;

    @Column(name = "price_cost_unit_ex_tax", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("不含税成本单价")
    private double priceCostUnitExTax = 0;

    @Column(name = "refer_tax", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("参考成本")
    private double referTax = 0;

    @Column(name = "inner_refer_tax", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("内协参考成本")
    private double innerReferTax = 0;

    @Column(name = "estimated_commission", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("预估提成")
    private double estimatedCommission = 0;

    @Column(name = "inquiry_price_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("询价销售单价")
    private double inquiryPriceUnit = 0;  //通过价格审核后的

    @Column(name = "inquiry_price_limit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("询价销售限价")
    private double inquiryPriceLimit = 0;  //通过价格审核后的

    @Column(name = "inquiry_purchase_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("询价采购限价")
    private double inquiryPurchaseUnit = 0;  //通过价格审核后的

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "LOCATION_ID", referencedColumnName = "id", nullable = false)
    private Location location;  //仓库库区

    @Column(name = "remarks", length = 400)
    @Comment("门店备注")
    private String remarks;

    @Column(name = "purchase_remarks", length = 250)
    @Comment("采购备注")
    private String purchaseRemarks;

    @Column(name = "supplier_remarks", length = 250)
    @Comment("供应商备注")
    private String supplierRemarks;

//    @Column(name = "customer_remarks", length = 250)
//    @Comment("客户备注")
//    private String customerRemarks;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "main_sales_staff", referencedColumnName = "id")
    @Comment("销售人员")
    private PartyRole SalesStaff;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "original_product_id", referencedColumnName = "id")
    @Comment("原询价商品编码")
    private Product originalInquiryProduct;

    //可能用到字段
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "serve_type_id", referencedColumnName = "id")
    @Comment("服务类型")
    private ServeType serveType;

    @Transient
    private boolean needInquiry = true;


    @Column(name = "product_rule", nullable = false, columnDefinition = "number(1,0) default 1")
    @Comment("带安标记")
    private boolean productRule;

    @Column(name = "use_coupon", nullable = false, columnDefinition = "number(1,0) default 0")
    @Comment("是否使用卡券")
    private boolean useCoupon;

    @States(name = "待跟踪标记", values = {
            @State(id = "normal", name = "正常"),
            @State(id = "wait", name = "待跟踪"),
            @State(id = "finish", name = "完成")
    })
    @Column(name = "track_state", length = 10, nullable = false)
    private String trackState = "normal";   //可能用到字段

    @States(name = "派工标记", values = {
            @State(id = "begin", name = "未派工"),
            @State(id = "dispatch", name = "派工"),
    })
    @Column(name = "dispatch_state", length = 10, nullable = false)
    private String dispatchState = "begin";   //可能用到字段

    @Column(name = "termination_flag", nullable = false, columnDefinition = "number(1,0) default 1")
    @Comment("终止标记")
    private boolean terminationFlag = false;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "termination_date")
    @Comment("终止日期")
    private Date terminationDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "termination_uid", referencedColumnName = "id")
    @Comment("终止人")
    private PartyRole terminationUid;

    @JSONField(format = DateUtil.SHOW_DATETIME_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "exchange_date")
    @Comment("冲红日期")
    private Date exchangeDate;

    @Column(name = "quality_test_date")
    @Comment("质检时间")
    private Date qualityTestDate;

    public void setQualityTestDate(Date qualityTestDate) {
        if(qualityTestDate != null && this.qualityTestDate != null){
            throw new RuntimeException("该明细已经质检过，无需质检，商品名称" + this.product.getName());
        }
        this.qualityTestDate = qualityTestDate;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "quality_test_uid", referencedColumnName = "id")
    @Comment("质检人")
    private PartyRole qualityTestUid;

    @Column(name = "finish_date")
    @Comment("完成时间")
    private Date finishDate;

    @Column(name = "quality_flag", nullable = false, columnDefinition = "number(1,0) default 1")
    private boolean qualityFlag = true;

    @Column(name = "need_quality_flag", nullable = false, columnDefinition = "number(1,0) default 0")
    @Comment("本明细是否需要质检")
    private boolean needQualityFlag = false; //2020-08-12 双边质检（工时仍需质检+ 外协完工设置该标记为1，添加进质检队列）

//    @Column(name = "recycle")
//    @Comment("旧件需回收标记")
//    private boolean recycle = false;
//
//    @Column(name = "c_recycle")
//    @Comment("客户回收标记")
//    private boolean cRecycle = false;
//
//    @Column(name = "insurance_recycle")
//    @Comment("保险回收标记")
//    private boolean insuranceRecycle = false;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "main_saler_id", referencedColumnName = "id")
    @Comment("主销")
    private PartyRole mainSaler;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "sup_saler_id", referencedColumnName = "id")
    @Comment("辅销")
    private PartyRole supSaler;

    @Column(name = "service_plan_item_source", length = 16)
    @Comment("来源方案明细号")
    private String servicePlanItemSource;   //用于做操作，方便从另外一个方案找到初始方案明细

    ////是否需要询价标记
    //@Transient
    //@Comment("是否需询价")
    //private boolean isNeedInquiry = false;

    @Column(name = "old_inquiry_number", length = 32)
    @Comment("老框架询价单号")
    private String oldInquiryNumber;

    @Column(name = "expected_arrival_time", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("预计到货时长")
    private double expectedArrivalTime = 0;

//    @ManyToOne(fetch = FetchType.LAZY)
//    @JoinColumn(name = "logistics_mode_id", referencedColumnName = "id")
//    @Comment("物流方式")
//    private Enumeration logisticsMode;

    @Column(name = "carrier_id")
    @Comment("承运商编码")
    private String carrierId;

    @Column(name = "carrier_name")
    @Comment("承运商名称")
    private String carrierName;

    @Transient
    private double expectedArrivalTimeTemp;
    public double getExpectedArrivalTimeTemp(){
        if(this.inquiryGooodsState != null  &&  "2".equals(this.inquiryGooodsState) ){
            return Arith.round(this.expectedArrivalTime / 24,3);
        }
        return 0;
    }
    @Column(name = "quality_warranty", length = 32)
    @Comment("质保期")
    private String qualityWarranty;

    @Column(name = "quality_mileage", length = 32)
    @Comment("质保里程")
    private String qualityMileage;

    public void setInquiryGooodsState(String inquiryGooodsState) {
        try{
            inquiryGooodsState = String.valueOf((int)Double.parseDouble(inquiryGooodsState));
        }catch (Exception e){

        }
        this.inquiryGooodsState = inquiryGooodsState;
    }

    @Column(name = "inquiry_gooods_state", length = 32)
    @Comment("货源状态(0无货|1现货|2需订货|3现货（价格前置）)")
    private String inquiryGooodsState;

    @Comment("货源")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "goods_source", referencedColumnName = "id")
    private Enumeration goodsSource;//002405 :第三方货源 002406 :集群货源

    /**
     * 判断卡内商品是否需要自动转外协
     * @return
     */
    public boolean isNeedAutoTransitionAssistTypeForKN() {
        if (this.getProduct()==null)return false;
        if (this.getProduct().getBrand()==null)return false;
        boolean equals = "师人订制".equals(this.getProduct().getBrand().getName());
//        if (this.goodsSource!=null)equals = goodsSource.getId().equals("002406");
//        if (this.goodsSource==null)equals = false;
        if (this.servicePlan.getChannel()==null) return false;
        if ("师人订制".equals(this.servicePlan.getChannel().getName())&&this.goodsSource==null)
            throw new RuntimeException("渠道为师人订制的货源不能为空!");
        return equals;
    }

    @Transient
    private boolean needAutoTransitionAssistTypeForKN = false;

    @Column(name = "cross_order_work_mark", length = 16)
    @Comment("跨单施工标记")
    private String crossOrderWorkMark = "0";

    @Transient
    @Comment("询价类型0询库存1询价格")
    private Integer inquiryType = 1;


    @States(name = "询价勾选标记", values = {
            @State(id = "false", name = "不选择"),
            @State(id = "true", name = "选择")
    })
    @Column(name = "inquiry_select_state", nullable = false, columnDefinition = "number(1,0) default 1")
    private boolean inquirySelectState = true;


    public void changerInquirySelectFlag(Integer inquirySelectFlag){
        this.inquirySelectFlag = inquirySelectFlag;
    }

    @Comment("询价配件选择功能")//改用为同意必修选择过滤
    @Column(name = "inquiry_select_flag", columnDefinition = "number(1,0) default 1")
    private Integer inquirySelectFlag = 1;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "platform_id", referencedColumnName = "id")
    @Comment("平台")
    private PartyRole platform;

    @Column(name = "old_frame_source_from", length = 16)
    @Comment("老框架方案号")
    private String oldFrameSourceFrom; //来源

    @Comment("协助类型")
    @States(name = "协助类型", values = {
            @State(id = "normal", name = "普通"),
            @State(id = "inner", name = "内协"),
            @State(id = "outer", name = "外协")
    })
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "assist_type", columnDefinition = "varchar2(120) default 'ServicePlanItem.assistType.normal'", referencedColumnName = "id")
    private BusinessAttributeValue assistType;

    public String getMapAddress() {
        if (mapAddress!=null&&LogicalUtil.notIn(mapAddress.trim(),"","[]")){
            try{
                JSONArray array = JSONArray.parseArray(mapAddress);
                array.forEach(o -> {
                    com.alibaba.fastjson.JSONObject jsonObject = (com.alibaba.fastjson.JSONObject) o;
                    if (jsonObject.containsKey("url")){
                        String url = StringUtil.urlGetFile(jsonObject.getString("url"));
                        jsonObject.put("url",url);
                    }
                });
                return JSONArray.toJSONString(array);
            } catch(Exception e) {
                e.printStackTrace();
                this.getServicePlan().addErrorMsg("图片转换异常:"+e.getMessage());
            }
        }
        return mapAddress;
    }

    @File
    @Lob
    @Comment("图片地址")
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "map_address", columnDefinition = "CLOB")
    private String mapAddress;

    @Column(name = "tag_map_address", length = 4000)
    @Comment("图片地址-带标记")
    private String tagMapAddress;


    @Column(name = "quality_test_pic", length = 4000)
    @Comment("质检图片")
    private String qualityTestPic;

    @Column(name = "part_code", length = 4000)
    @Comment("零件编码")
    private String partCode;

    @Column(name = "part_name", length = 4000)
    @Comment("零件名称")
    private String partName;

    @Column(name = "image_sn")
    @Comment("图号")
    private String imageSN;


    @Column(name = "VIP_DISCOUNT_TYPE")
    @Comment("会员权益类型")
    private String vipDiscountType;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "crossIC_id", referencedColumnName = "id")
    @Comment("异业合作类型")
    private CrossIC crossIC;

    @Column(name = "exchance_code", length = 512)
    @Comment("服务兑换码")
    private String exchanceCode;

    @Transient
    private List exchanceCodeList;
    public List getExchanceCodeList(){
        if(this.exchanceCode == null) return null;
        if("".equals(this.exchanceCode)) return null;
        return JSONArray.parseArray(this.exchanceCode);
    }

    @Column(name = "qty_exchance_code", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("兑换码数量")
    private double qtyExchanceCode = 0;

    @Column(name = "qty_exchance_amount", nullable = false, columnDefinition = ApesConst.FIELD_QTY_16_4_0)
    @Comment("兑换商品数量")
    private double qtyExchanceAmount = 0;

    @Column(name = "deduction_unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("异业抵扣单价")
    private double deductionUnit = 0;

    @Column(name = "deduction_amount", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("异业抵扣金额")
    private double deductionAmount = 0;

    @Column(name = "self_supporting_Unit", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("顾客自费单价")
    private double selfSupportingUnit = 0; //该字段2021-01-14 弃用

    @Column(name = "self_supporting_amount", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("顾客自费金额")
    private double selfSupportingAmount = 0; //该字段2021-01-14 弃用

    @Column(name = "match_flag", nullable = false, columnDefinition = "number(1,0) default 0")
    @Comment("异业匹配")
    private boolean matchFlag = false;

    @Column(name = "discount_amount", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("折扣金额")
    private double discountAmount = 0;

    @Column(name = "CROSS_ACCOUNT_PRICE", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("赋能结算价")
    private double crossAccountPrice = 0;

    @Column(name = "CROSS_CUSTOMER_PRICE", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("客户支付价")
    private double crossCustomerPrice = 0;

    @Column(name = "CROSS_PRICE_COST", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("合作成本价")
    private double crossPriceCost = 0;

    @Column(name = "PRICE_APPROVAL_AMT", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("通过价格审核的价格")
    private double priceApprovalAmt = 0;


    public double obtainDiscountAmount(){ //同等抵扣券数量 * (优惠单价 - 抵扣单价 - 顾客自费单价)
        if(this.qtyExchanceCode == 0 || !this.matchFlag){
            return 0;
        }
        Map resultMap = SpringManager.getBean(TaxService.class)
                .getSaleTax(servicePlan.getCompany(), product)
                .computeAll(servicePlan.getCompany(), this.pftPriceUnit - this.deductionUnit - this.selfSupportingUnit, this.qtyExchanceCode);
        double result = ((Double) resultMap.get("totalIncluded")).doubleValue();
        if(result < 0) result = 0;
        return result ;
    }

    @Column(name = "real_pay_amount", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("顾客实际金额")
    private double realPayAmount = 0;
    public void setRealPayAmount(double realPayAmount){
        if (this.crossIC==null){
            this.realPayAmount = this.salesAmount;
        }else {
            this.realPayAmount = realPayAmount;
        }

    }


    //    public double obtainRealPayAmount(){ // （销售数量 - 兑换券数量） * 优惠单价 +
//        if(this.qtyExchanceCode == 0){
//            return 0;
//        }
//        double result = 0.0;
//        if(this.matchFlag){ //匹配
//            Map resultMap = SpringManager.getBean(TaxService.class)
//                    .getSaleTax(servicePlan.getCompany(), product)
//                    .computeAll(servicePlan.getCompany(), this.pftPriceUnit, this.saleQty - this.qtyEnd - this.qtyExchanceCode);
//            double result1 = ((Double) resultMap.get("totalIncluded")).doubleValue();
//
//            resultMap = SpringManager.getBean(TaxService.class)
//                    .getSaleTax(servicePlan.getCompany(), product)
//                    .computeAll(servicePlan.getCompany(), this.selfSupportingUnit, this.qtyExchanceCode);
//
//            double result2 = ((Double) resultMap.get("totalIncluded")).doubleValue();
//            result = result1 + result2;
//        }else{ //不匹配
//            Map resultMap = SpringManager.getBean(TaxService.class)
//                    .getSaleTax(servicePlan.getCompany(), product)
//                    .computeAll(servicePlan.getCompany(), this.pftPriceUnit, this.saleQty - this.qtyEnd);
//
//            double result1 = ((Double) resultMap.get("totalIncluded")).doubleValue();
//            resultMap = SpringManager.getBean(TaxService.class)
//                    .getSaleTax(servicePlan.getCompany(), product)
//                    .computeAll(servicePlan.getCompany(), this.deductionUnit, this.qtyExchanceCode);
//            double result2 = ((Double) resultMap.get("totalIncluded")).doubleValue();
//        }
//        if(result < 0) result = 0;
//        return result ;
//    }
//    @ManyToOne(optional = false)
//    @JoinColumn(name = "maintenance_order", referencedColumnName = "ID")
//    @Comment("工单")
//    private MaintenanceOrder maintenanceOrder;
//    @Transient
//    private MaintenanceOrder maintenanceOrder;  //查找工单明细方法
    public MaintenanceOrder returnMaintenanceOrder(){
        List<MaintenanceOrder> maintenanceOrders = SpringManager.getBean(MaintenanceOrderRepository.class).findAll(
                JpaDsl.toCriteriaByEq("servicePlanItem.id",this.id)
        );
        return maintenanceOrders.stream().filter(maintenanceOrder -> {
            return !"out".equals(maintenanceOrder.getBusinessType());
        }).findFirst().orElse(null);
    }

    @Comment("单位客户")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "unit_Client", referencedColumnName = "id")
    private PartyRole unitClient;

    @Column(name = "relevance_work_order", length = 16)
    @Comment("关联工单号（配件绑定工单关系）")
    private String relevanceWorkOrder; //来源

    @Column(name = "unique_value", length = 4000)
    @Comment("唯一值")
    private String uniqueValue;

    @Column(name = "price_forward")
    @Comment("渠道")
    private String priceForward;//1：价格前置标记 2：新平台询价 3：询价执行表 4：三头六臂 5：巴图鲁 6：外采

    @Column(name = "pack_id", length = 128)
    @Comment("套包编码")
    private String packId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "batch_code", referencedColumnName = "id")
    @Comment("商品批次内码")
    private InventoryBatch inventoryBatch; // 指定商品批次（带安/服务）

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "supplier_id", referencedColumnName = "id")
    @Comment("供应商")
    private PartyRole supplier; //供应商

    /*@Column(name = "broker_product_pick", nullable = false, columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("代理拿货价")
    private double brokerProductPick = 0;*/

    @Column(name = "commission_amount", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("佣金额")
    private double commissionAmount = 0;

    @Column(name = "fullerton_amount", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("富登金币")
    private double fullertonAmount = 0;

    @Comment("报价结果Id")
    @JoinColumn(name = "quote_result_id")
    private String quoteResultId;

    @Transient
    MaintenanceOrder maintenanceOrder;

    @Transient
    private Integer selectFlag;

    @Transient
    private Map addInfo;

    @Transient
    private boolean selected;

    @Transient
    private String haveOffice = "暂无报价";
    public String getHaveOffice(){
        if (this.uniqueValue!=null)return "已有报价";
        return this.haveOffice;
    }
    @Transient
    private String inquirySource = "none";
    /**
     * 换算销售数量
     * @return
     */
    @Transient
    private double salesVolume;
    public double getSalesVolume() {
        double qty = 0;
        try {
            qty = uom.computeQty(saleQty, uom, false);
            if(qty == 0){
                return this.saleQty;
            }
            return qty;
        }catch (Exception e){
            return this.saleQty;
        }
    }


    @Transient
    private Integer serviceStateFlag;
    public Integer getServiceStateFlag(){
        if(this.isServiceState()) return 1;
        return 0;
    }

    @Transient
    private String uomName;

    /**
     * 计算金额
     */
    public Double SaleAmount() {
        Map result = SpringManager.getBean(TaxService.class)
                .getSaleTax(servicePlan.getCompany(), product)
                .computeAll(servicePlan.getCompany(), Arith.roundUp(this.pftPriceUnit,2), this.getSaleQty() - this.getQtyEnd());
        return ((Double) result.get("totalIncluded")).doubleValue();
    }

    /**
     * 计算结算金额
     * 销售数量 - 终止数量 = 卖的数量（质检前，配件的话必须领用 + 终止 =  销售）
     * @return
     */
    public Double balanceAmount(){
        if(this.product != null && this.product.getProductGroup() != null){
            if("20".equals(this.product.getProductGroup().getId())){
                return Arith.round(Arith.mul(this.getSaleQty(),this.getPftPriceUnit()),0);
            }else if("10".equals(this.product.getProductGroup().getId())){
                return Arith.round(Arith.mul(this.getQtyReceive(),this.getPftPriceUnit()),0);
            }else{
                throw new RuntimeException("统计结算金额错误");
            }
        }
       return 0.0;
    }

    @Transient
    private Integer qualityTestFlag;
    public Integer getQualityTestFlag(){
        if(this.serviceState == true && this.terminationFlag == false){
            return 1;
        }
        return 0;
    }


    @Transient
    private Double balanceAmount;
    public Double getBalanceAmount(){
        return balanceAmount();
    }

    /** 内协油漆凭证使用 **/
    @Column(name = "paint_Price", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("油漆价格")
    private Double paintPrice; // 油漆价格

    @Column(name = "paint_purchase_Price", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("油漆采购价格")
    private Double paintPurchasePrice; // 油漆采购价格

    @Column(name = "paint_Flag", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE) // nullable = false,
    @Comment("油漆商品标记")
    private boolean paintFlag = false; // 油漆商品标记

    @Column(name = "show_price_unit_tips", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("销售单价提示")
    private boolean showPriceUnitTips = false;

    @Column(name = "paint_type", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("油漆类别(0:水性;1:油性)")
    private int paintType = 0;  // 油漆类别(0:水性;1:油性)

    @Column(name = "fourS_Price", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("4s价格")
    private Double fourSPrice; // 4s价格

    @Column(name = "estimated_commission_flag", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("预估提成异步计算标记")
    private String estimatedCommissionFlag; // 预估提成计算标记

    public ServicePlan queryServicePlanByItem(){
        if(this.servicePlan != null) return this.servicePlan;
        return SpringManager.getBean(ServicePlanItemRepository.class).findOne(this.id).getServicePlan();
    }

    public String returnServeType(){
        String id = this.getProduct().queryServeType().getId();
        if(id.equals("001") || id.equals("002")){
            return "cosmetology";
        }else if(id.equals("007")){
            return "sprayPaint";
        }else{
            return "machineRepa";
        }
    }

    /**
     * 判断配件，在某些操作写处于那种状态
     * @return
     */
    public String returmItemState(){
        if(this.getSaleQty() == this.getQtyEnd()){
            return "termination";
        }else if(this.getSaleQty() == this.getQtyEnd() + this.getQtyReceive()){
            return "finish";
        }else{
            return "unDone";
        }
    }

    /**
     * 获取商品规则
     * @return productRule
     */
    public int calcProductRule() {
        int productRule;
        if (this.getServicePlan() == null) {
            this.servicePlan = SpringManager.getBean(ServicePlanItemRepository.class).findOne(this.id).getServicePlan();
        }

        /**是否跨公司**/
        ServicePlanItem childServicePlanItem = SpringManager.getBean(ServicePlanceService.class).findCBPForServicePlan(this);
        boolean isCross = (childServicePlanItem != null && !childServicePlanItem.getServicePlan().getCompany().equals(this.getServicePlan().getCompany()))
                || this.oldFrameSourceFrom != null;

        /** 定损单据单独处理 **/
        if ("LossQuotation".equals(this.servicePlan.getSourceBusinessType())) {

            if (this.getProduct().getProductGroup().getId().equals("10")) {
                if (!isCross) { // 不跨公司的情况：基地自己接车维修
                    productRule = getProductRule(false);
                } else {
                    productRule = 0;
                }
            } else {
                // 非配件部分
                productRule = 30;

                //  增加判断是否为定损工单内协
                if ( isCross && "lossSomeAssist".equals(this.servicePlan.getPlanType())) {
                    productRule = getProductRule(true);
                }

                // 增加判断是否为整单内协之后，带安外协
                if ( (this.getAssistType().getCode().equals("outer") || this.getLocation().getUsage().isProductRule()) && this.getInventoryBatch() == null){
                    productRule = 10;
                }

                // 增加判断是否为自定损维修之后，外协部分
                if ( (this.getAssistType().getCode().equals("outer") || this.getLocation().getUsage().isProductRule()) &&  this.getInventoryBatch() != null) {
                    productRule = 20;
                }

            }
            return productRule;
        }

        productRule = getProductRule(isCross);
        return productRule;
    }

    private int getProductRule(boolean isCross) {
        int productRule;
        if (this.getAssistType().getCode().equals("inner")) { /**内协**/
            if (isCross) {
                if (this.getInventoryBatch() == null) throw new RuntimeException("跨公司内协未产生采购");
                productRule = 20;
            } else {
                if (this.getInventoryBatch() != null) {
                    productRule = 20;
                } else if (this.getLocation().getUsage().isProductRule()) {
                    productRule = 10;
                } else if (this.getProduct().getProductGroup().getId().equals("10")) { /**一般商品**/
                    productRule = 0;
                } else { /**服务商品(非带安)**/
                    productRule = 30;
                }
            }
        } else if (this.getAssistType().getCode().equals("normal") && this.getLocation().getUsage().isProductRule() ) { /**带安商品自己服务**/
            productRule = 30;
        } else if (this.getAssistType().getCode().equals("outer") || this.getLocation().getUsage().isProductRule()) { /**带安（外协）**/
            if (this.getInventoryBatch() != null) {
                productRule = 20;
            } else {
                productRule = 10;
            }
        } else if (this.getProduct().getProductGroup().getId().equals("10")) { /**一般商品**/
            productRule = 0;
        } else { /**服务商品(非带安)**/
            productRule = 30;
        }
        return productRule;
    }

    /**
     * true : 当前行可种植
     * 判断是否可终止
     * （当前明细行为终止，有老框架来源，类型为非normol状态都是表示不能终止的）
     * @return
     */
    public boolean checkCanEnd(){
//        MaintenanceOrder maintenanceOrder = this.servicePlan.getConfirmDate()==null||this.servicePlan.getTerminationDate()!=null?null:this.returnMaintenanceOrder();
//        if( this.terminationDate != null || this.getAssistType() == null || !"ServicePlanItem.assistType.normal".equals(this.getAssistType().getId()) || this.getOldFrameSourceFrom() != null) return false;
        if (this.terminationDate != null ||
                this.getAssistType() == null ||
                (this.getAssistType().getId().equals("ServicePlanItem.assistType.outer")) ||
                (this.innerServicePlanItem != null) ||
                this.getOldFrameSourceFrom() != null
        )
            return false;
        return true;
    }

    /**
     * 判断当前单据是否异业或者领用
     * @return
     */
    public String getTerminationType() {
        if (crossIC!=null&&qtyReceive>0)return "1";
        if (crossIC!=null)return "2";
        if (qtyReceive>0)return "3";

        return terminationType;
    }

    @Transient
    private String terminationType = "0";

    @Transient
    private String note;//询价备注说明

    @Transient
    private String oldPicture;//询价旧件图片

    @Column(name = "root_in", length = 128)
    @Comment("配件译码来源")
    private String rootIn;//0=巴图鲁，1=兆配，2=车宝
    public Double getReferTaxProfit() {
        return Arith.round(this.salesAmount - (this.referTax * this.saleQty),2);
    }

    @Transient
    private Double referTaxProfit;//参考毛利


    public boolean checkExternalInquiry(){
        if (this.getOldInquiryNumber()!=null&&this.getOldInquiryNumber().startsWith("WC"))return true;
        return false;
    }

}
